using System;
using System.Collections.Generic;
using System.Linq;
using GP.Logic.Model;

namespace GP.Logic
{
    public class DoctorService
    {
        private readonly GpContext _context;
        public DoctorService()
        {
            _context = new GpContext();
        }

        public ICollection<Doctor> GetDoctorsExcept()
        {
            long doctorId = GetDoctorID();
            return _context.Doctors.Where(a => a.DocId != doctorId).ToList();
        }

        public ICollection<Doctor> GetDoctorsExcept(IEnumerable<long> ids)
        {
            return _context.Doctors.Where(a => !ids.Contains(a.DocId)).ToList();
        }

        public ICollection<Citizen> GetPatients()
        {
            return null;
        }
        
        public long GetDoctorID()
        {
            var doctorUsername = PageData.GetDoctorUsername();
            return _context.GpSysUsers.Single(a => a.Username == doctorUsername).DocId;
        }

        public Citizen GetCitizen()
        {
            var citizenId = PageData.GetCitizenId();
            var doctorId = GetDoctorID();
            Citizen currentCitizen = _context.Citizens.SingleOrDefault(a => a.CitizenId == citizenId && (a.DocId == doctorId || a.GratedAccessTos.Any(b => b.DocId == doctorId)) );
            return currentCitizen;
        }

        public Doctor CreateNewDoctor()
        {
            var doctor = new Doctor();
            doctor.Name = "n/a";
            doctor.LicensNr = "please enter a valid LicensNr";
            doctor.Phone = "";
            doctor.Email = "";
            _context.Doctors.Add(doctor);
            _context.SaveChanges();

            return doctor;
        }

        public void DeleteDoctor(long id)
        {
            Doctor single = _context.Doctors.Single(a => a.DocId == id);
            _context.Doctors.Remove(single);
            _context.SaveChanges();
        }

        public List<Doctor> GetDoctors()
        {
            List<Doctor> doctors = _context.Doctors.ToList();
            return doctors;
        }

        public Doctor GetDoctor()
        {
            string doctorUsername = PageData.GetDoctorUsername();
            GpSysUser gpSysUser = _context.GpSysUsers.Single(a => a.Username == doctorUsername);
            return gpSysUser.Doctor;
        }

        public Doctor GetDoctor(long id)
        {
            return _context.Doctors.Single(a => a.DocId == id);
        }

        public void SaveDoctor(long docId, Doctor doctor)
        {
            Doctor single = GetDoctor(docId);

            single.Name = doctor.Name ?? "";
            single.LicensNr = doctor.LicensNr ?? "";
            single.Email = doctor.Email ?? "";
            single.Phone = doctor.Phone ?? "";

            _context.SaveChanges();
        }

        public GpSysUser CreateNewUser(long docId)
        {
            var user = new GpSysUser
                           {
                               DocId = docId,
                               Username = Guid.NewGuid().ToString("N").Substring(0, 12),
                               Password = Guid.NewGuid().ToString("N").Substring(0, 12)
                           };
            _context.GpSysUsers.Add(user);
            _context.SaveChanges();
            return user;
        }

        public GpSysUser GetUser(long userId)
        {
            return _context.GpSysUsers.Single(a => a.UserId == userId);
        }

        public GpSysUser SaveUser(long userId, GpSysUser newUser)
        {
            GpSysUser user = GetUser(userId);
            user.Username = newUser.Username;
            user.Password = newUser.Password;
            _context.SaveChanges();
            return user;
        }

        public void DeleteUser(long userId)
        {
            GpSysUser user = GetUser(userId);
            _context.GpSysUsers.Remove(user);
            _context.SaveChanges();
        }

        public ICollection<Doctor> GetDoctorsWhichDontHaveGrantedAccess(long citizenId)
        {
            List<long> longs = _context.GrantedAccessTos.Where(a => a.CitizenId == citizenId).Select(a => a.DocId).ToList();

            ICollection<Doctor> doctorsExcept = GetDoctorsExcept(longs);

            return doctorsExcept;
        }

        public bool HasAccessTo(long citizenId)
        {
            Doctor doctor = GetDoctor();

            Citizen singleOrDefault = _context.Citizens.SingleOrDefault(a => a.CitizenId == citizenId && a.DocId == doctor.DocId);
            if (singleOrDefault != null)
                return true;

            return _context.Citizens.Any(a => a.CitizenId == citizenId && a.GratedAccessTos.Any(b => b.DocId == doctor.DocId));
        }
    }
}